package kevin.framework.basic.common.ui;

import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import kevin.framework.basic.common.thread.UrlInfoThreadHodler;
import kevin.framework.basic.common.user.LoginUser;
import kevin.framework.basic.common.utils.AnnotationValid;
import kevin.framework.basic.common.utils.DateUtils;
import kevin.framework.basic.common.utils.IServiceValid;
import kevin.framework.basic.common.utils.UrlInfo;

/**
 * @ClassName: AdminControllerHelper
 * @Description: TODO
 * @author kevin.huang
 * @date 2015年12月21日 下午4:33:15
 */
public class AdminControllerHelper {

	private static Logger logger = LoggerFactory.getLogger(AdminControllerHelper.class);

	public static Map<String, Field[]> fieldMap = new HashMap<String, Field[]>();
	private static Map<String, Method> methodMap = new HashMap<String, Method>();

	public static UrlInfo getControllerAndCmd(HttpServletRequest request) {

		UrlInfo info = UrlInfoThreadHodler.get();
		if (info == null) {
			info = new UrlInfo();

			String requestUrl = request.getRequestURI();

			String contextPath = request.getContextPath() + "/";

			info.setCtx(contextPath);

			if (requestUrl.equals(contextPath)) {
				info.setRootRequest(true);
			}

			info.setUrl(requestUrl);
			String tmpStr = requestUrl;
			if (!"/".equals(contextPath)) {
				tmpStr = requestUrl.replace(contextPath, "");
			}				
			String method = request.getMethod();

			// 按规范 此为请求页面的url
			if ("GET".equals(method) && requestUrl.contains("/page/")) {
				tmpStr = tmpStr.replaceAll("/page/\\S*", "/page");
			}

			String[] tmpArr = tmpStr.split("/");
			StringBuffer controller = new StringBuffer();
			controller.append("/");
			String cmdString = null;
			for (int i = 0, len = tmpArr.length; i < len; ++i) {
				if (i < len - 1) {
					controller.append(tmpArr[i]);
					if (i < len - 2) {
						controller.append("/");
					}						
				} else {
					cmdString = tmpArr[i];
				}
			}
			String cmdParam = request.getParameter("cmd");
			if (StringUtils.isNoneEmpty(cmdParam)) {
				cmdString = cmdParam;
			}

			String authorCtrlString = request.getParameter("authctl");

			if (StringUtils.isNotEmpty(authorCtrlString)) {
				info.setAuthController(authorCtrlString);
			}

			info.setController(controller.toString().replace("//", "/"));
			info.setCmd(cmdString);

			UrlInfoThreadHodler.set(info);

			if (logger.isDebugEnabled()) {
				logger.debug(info.toString());
			}
		}
		request.setAttribute("cmd", info.getCmd());
		return info;
	}

	/**
	 * @Title: getObjectFromRquest @Description: 从请求中提前数据创建实体对象 @param formObject
	 *         可以是HttpServletRequest 或者 map<String,String>集合 @param entityClass
	 *         实体类的class @param idClass id属性的class @param isUpdated 是否是用于更新操作的
	 *         createUserId、createTime特殊字段处理 @return @throws
	 */
	@SuppressWarnings("unchecked")
	public static <T extends Serializable> T getObjectFromRequest(LoginUser user, Object formObject,
			Class<?> entityClass, Class<?> idClass, boolean isUpdated) throws Exception {

		T bean = (T) entityClass.newInstance();
		for (Class<?> superClass = entityClass; superClass != Object.class; superClass = superClass.getSuperclass()) {

			String clsName = entityClass.getName();
			Field[] fields = fieldMap.get(clsName);

			if (fields == null) {
				fields = superClass.getDeclaredFields();
				fieldMap.put(clsName, fields);
			}

			boolean isRequest = formObject instanceof HttpServletRequest;
			for (Field field : fields) {
				String fieldName = field.getName();
				if (fieldName.equalsIgnoreCase("serialVersionUID")) {
					continue;
				}
				String tmpVal = null;
				if (isRequest) {
					tmpVal = ((HttpServletRequest) formObject).getParameter(fieldName);
				} else {
					tmpVal = ((Map<String, String>) formObject).get(fieldName);
				}
				// 特殊字段处理
				if (!isUpdated && fieldName.equalsIgnoreCase("createTime")) {
					tmpVal = DateUtils.formatCurrentDateTime("yyyy-MM-dd HH:mm:ss");
				}
				if (!isUpdated && fieldName.equalsIgnoreCase("createUserId")) {
					// tmpVal = String.valueOf(user.getId()); 测试注释
				}
				if (tmpVal == null) {
					continue;
				}					
				String _value = tmpVal;// URLDecoder.decode(tmpVal,"utf-8");
				PropertyDescriptor pd = null;

				String methodKey = clsName + fieldName;

				Method method = methodMap.get(methodKey);
				if (method == null) {
					try {
						pd = new PropertyDescriptor(fieldName, entityClass);
						method = pd.getWriteMethod();
						method.setAccessible(true);
						methodMap.put(methodKey, method);
					} catch (Exception e) {
						e.printStackTrace();
						continue;
					}
				}
				Class<?> clazz = field.getType();
				if ("id".equals(fieldName)) {
					clazz = idClass;
				}
				if (clazz.isArray()) {
					// 待实现
				} else if (clazz.isEnum()) {
					// 待实现
				} else {
					String simpleName = clazz.getSimpleName().toLowerCase();
					if (simpleName.equalsIgnoreCase("string")) {
						method.invoke(bean, _value);
					} else if (simpleName.equalsIgnoreCase("date")) {
						if (!_value.equalsIgnoreCase("")) {
							if (_value.matches("\\d{4}-\\d{2}-\\d{2}")) {
								method.invoke(bean, DateUtils.parseDateTime(_value, "yyyy-MM-dd"));
							} else {
								method.invoke(bean, DateUtils.parseDateTime(_value, "yyyy-MM-dd HH:mm:ss"));
							}
						}
					} else if (simpleName.equalsIgnoreCase("boolean")) {
						String tmp = _value.toLowerCase();
						if (tmp.equalsIgnoreCase("0") || tmp.equalsIgnoreCase("false")) {
							method.invoke(bean, false);
						} else {
							method.invoke(bean, true);
						}
					} else {
						if (!_value.equalsIgnoreCase("")) {
							Object obj = ConvertUtils.convert(_value, clazz);
							method.invoke(bean, obj);
						}
					}
				}
			}
		}
		return bean;
	}

	public static <T extends Serializable, K extends Serializable> String validEntityBean(T bean,
			HashSet<String> excFileds, IServiceValid svcValuid, HttpServletRequest request) {
		AnnotationValid<T, K> valid = new AnnotationValid<T, K>();
		String validRes;
		try {
			validRes = valid.valid(bean, excFileds, svcValuid, request);
		} catch (Throwable e) {
			validRes = "validate is expction！";
			logger.error("", e);
		}
		return validRes.toString();
	}

}
